package com.gitee.kamismile.stone.basic.data.application.service;

import com.gitee.kamismile.stone.basic.data.application.req.command.dep.SysDepCreate;
import com.gitee.kamismile.stone.basic.data.application.req.command.dep.SysDepEdit;
import com.gitee.kamismile.stone.basic.data.application.req.query.dep.DepQuery;
import com.gitee.kamismile.stone.basic.data.domain.sysDep.repository.entity.SysDep;
import com.gitee.kamismile.stone.basic.data.domain.sysDep.service.ISysDepDomainService;
import com.gitee.kamismile.stone.basic.data.infrastructure.enums.CommonErrorEnum;
import com.gitee.kamismile.stone.basic.data.infrastructure.enums.DepErrorEnum;
import com.gitee.kamismile.stone.basic.data.infrastructure.utils.CriteriaQueryBuilder;
import com.gitee.kamismile.stone.commmon.exception.BusinessException;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validator;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.relational.core.query.Criteria;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import reactor.core.publisher.Mono;

import java.util.Optional;

@Component
public class SysDepServiceApplicationService {
    @Autowired
    private ISysDepDomainService iSysDepDomainService;
    @Autowired
    private Validator validator;

    public Mono<SysDep> save(SysDepCreate sysDepCreate, Integer nTenantId) {
        Assert.notNull(nTenantId, CommonErrorEnum.TenantNotFound.getMessage());


        SysDep sysDep = new SysDep();
        BeanUtils.copyProperties(sysDepCreate, sysDep);
        sysDep.setnTenantId(nTenantId);
        return iSysDepDomainService.saveOrUpdate(sysDep);
    }


    public Mono<SysDep> update(SysDepEdit sysDepEdit, Integer nTenantId) {
        Assert.notNull(nTenantId, CommonErrorEnum.TenantNotFound.getMessage());

        return iSysDepDomainService.findAndCheckDepById(sysDepEdit.getnSysDepId(), nTenantId)
                .flatMap(v -> {
                    SysDep sysDep = new SysDep();
                    BeanUtils.copyProperties(sysDepEdit, sysDep);
                    return iSysDepDomainService.saveOrUpdate(sysDep);
                });

    }

    public Mono<Void> deleteDepById(Integer nSysDepId, Integer nTenantId) {
        Assert.notNull(nTenantId, CommonErrorEnum.TenantNotFound.getMessage());

        return iSysDepDomainService.findAndCheckDepById(nSysDepId, nTenantId)
                .flatMap(v -> {
                            Mono<Void> removeMono = iSysDepDomainService.deleteDepById(nSysDepId);
                            Mono<Integer> modifyMono = iSysDepDomainService.modifyIslast(v.getnParentId(), nTenantId);
                            return removeMono.then(modifyMono).then();
                        }
                );
    }

    public Mono<Page<SysDep>> findDepPage(DepQuery depQuery) {
        validateQuery(depQuery);

        Criteria criteria = CriteriaQueryBuilder.builder()
                .eqIgnoreEmpty("nSysDepId", depQuery.getnSysDepId())
                .eqIgnoreEmpty("nParentId", depQuery.getnParentId())
                .likeIgnoreEmpty("sName", depQuery.getsName())
                .create();
        return iSysDepDomainService.findDepPage(depQuery.getCurrentPage(), depQuery.getPageSize(), criteria);
    }

    private void validateQuery(DepQuery depQuery) {
        Optional.ofNullable(
                        validator.validate(depQuery))
                .ifPresent(
                        info -> {
                            for (ConstraintViolation constraintViolation : info) {
                                throw new BusinessException(
                                        400, constraintViolation.getMessage());
                            }
                        });
    }


    public Mono<SysDep> findDepById(Integer nSysDepId, Integer nTenantId) {
        Assert.notNull(nTenantId, CommonErrorEnum.TenantNotFound.getMessage());
        Assert.notNull(nSysDepId, DepErrorEnum.DepNotNull.getMessage());
        return iSysDepDomainService.findDepById(nSysDepId, nTenantId);
    }

    /**
     * todo 根据部门ID 找到部门下面的人
     */
}
